package com.example.redisrabbitesintegeation.service.impl;

import com.example.redisrabbitesintegeation.common.exception.GlobalException;
import com.example.redisrabbitesintegeation.mapper.NewsMapper;
import com.example.redisrabbitesintegeation.model.entity.News;
import com.example.redisrabbitesintegeation.service.NewsService;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.highlight.Highlight;
import org.springframework.data.elasticsearch.core.query.highlight.HighlightField;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName NewsServiceImpl
 * @Description TODO
 * @Author Kx
 * @Date 2025/10/21 19:10
 * @Version 1.0
 */
@Service
public class NewsServiceImpl implements NewsService {
    @Autowired
    private NewsMapper newsMapper;
    @Autowired
    private ElasticsearchOperations elasticsearchOperations;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    /**
     * 定义存储新闻信息的Redis键前缀
    */
    private static final String NEWS_PREFIX = "news:code:";

    /**
     * @author: kx
     * @date: 2025/10/22 8:53
     * @description: 初始化索引
    */
    @PostConstruct
    private void initIndex() {
        if (!elasticsearchOperations.indexOps(com.example.redisrabbitesintegeation.model.document.News.class).exists()) {
            // 创建索引
            elasticsearchOperations.indexOps(com.example.redisrabbitesintegeation.model.document.News.class).create();
            // 创建 Mapping
            elasticsearchOperations.indexOps(com.example.redisrabbitesintegeation.model.document.News.class).putMapping();
        }
    }

    /**
     * @author: kx
     * @date: 2025/10/21 19:13
     * @param news : 新闻对象
     * @description: 发布新闻
    */
    @Override
    public void publishNews(News news) {
        try {
            // 调用 mapper 层发布新闻
            newsMapper.publishNews(news);
        } catch (Exception e) {
            throw new GlobalException(500, "发布新闻失败" + e.getMessage());
        }
    }

    /**
     * @author: kx
     * @date: 2025/10/21 20:05
     * @return java.util.List<com.example.redisrabbitesintegeation.model.entity.News>
     * @description: 查询所有新闻信息
    */
    @Override
    public List<com.example.redisrabbitesintegeation.model.document.News> getNewsList() {
        // 构建本地查询对象
        NativeQuery query = NativeQuery.builder().build();
        // 通过 search 方法查询所有的文档并返回命中结果集
        SearchHits<com.example.redisrabbitesintegeation.model.document.News> hits = elasticsearchOperations.search(query, com.example.redisrabbitesintegeation.model.document.News.class);
        // 返回结果集
        return hits.getSearchHits().stream().map(hit -> hit.getContent()).toList();
    }

    /**
     * @author: kx
     * @date: 2025/10/21 20:15
     * @param keyword : 关键字
     * @return java.util.List<com.example.redisrabbitesintegeation.model.entity.News>
     * @description: 搜索新闻信息并高亮显示
    */
    @Override
    public List<com.example.redisrabbitesintegeation.model.document.News> searchNewsWithHighlight(String keyword) {
        // 构建本地查询对象
        NativeQueryBuilder nativeQueryBuilder = NativeQuery.builder();
        // 构建高亮字段
        HighlightField highlightField1 = new HighlightField("title"); // 标题
        HighlightField highlightField2 = new HighlightField("author"); // 作者
        HighlightField highlightField3 = new HighlightField("classify"); // 分类
        HighlightField highlightField4 = new HighlightField("text"); // 内容
        // 封装成高亮对象
        Highlight highlight = new Highlight(List.of(highlightField1, highlightField2, highlightField3, highlightField4));
        // 执行高亮查询
        nativeQueryBuilder.withQuery(query -> query
                .multiMatch(multi -> multi
                        .fields("title", "author", "classify", "text")  // 指定要搜索的四个字段
                        .query(keyword)  // 搜索的关键词
                )
        );
        // 结果集
        return elasticsearchOperations.search(nativeQueryBuilder.withHighlightQuery(new HighlightQuery(highlight, com.example.redisrabbitesintegeation.model.document.News.class)).build(), com.example.redisrabbitesintegeation.model.document.News.class).getSearchHits().stream().map(hit -> hit.getContent()).toList();
    }

    /**
     * @author: kx
     * @date: 2025/10/21 20:37
     * @param newsId : 新闻id
     * @return com.example.redisrabbitesintegeation.model.entity.News
     * @description: 根据新闻id查询新闻信息
    */
    @Override
    public News getNewsById(Integer newsId) {
        // 判断新闻信息是否缓存
        if (redisTemplate.opsForValue().get(NEWS_PREFIX + newsId) == null) {
            // 获取新闻信息
            News news = newsMapper.getNewsById(newsId);
            if (news == null) {
                throw new GlobalException(500, "新闻不存在");
            }
            // 缓存新闻信息
            redisTemplate.opsForValue().set(NEWS_PREFIX + newsId, news, 1, TimeUnit.DAYS);
        }
        return (News) redisTemplate.opsForValue().get(NEWS_PREFIX + newsId);
    }

    /**
     * @author: kx
     * @date: 2025/10/22 19:06
     * @param newsId : 新闻id
     * @description: 删除新闻信息
    */
    @Override
    public void deleteNewsById(Integer newsId) {
        try {
            newsMapper.deleteNewsById(newsId);
        } catch (Exception e) {
            throw new GlobalException(500, "删除新闻失败" + e.getMessage());
        }
    }
}
